package jgcp.worker.process;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import jgcp.common.Task;
import jgcp.common.TaskDescription;
import jgcp.common.TaskStatus;
import jgcp.common.network.FileSender;
import jgcp.config.Configuration;
import jgcp.message.Message;
import jgcp.message.MessageType;
import jgcp.utils.Packer;
import jgcp.worker.service.WorkerService;
/**
 * 
 * @Date 31/05/2009
 * @author Peng Zhang(278819) Jie Zhao (288654)
 * @version 1.0
 */
public class Executer extends Thread {
	private Task task = null;
	private Process process = null;

	public Executer(Task t) {
		task = t;
	}

	public void cancel() {
		if (process != null) {
			process.destroy();
			while (this.isAlive())
				;
			task.setStatus(TaskStatus.CANCELED);
		}
	}

	public void run() {
		System.out.println("Executing task " + task.getTaskid());
		Message m = new Message();
		m.setType(MessageType.STATUS_RUNNING);
		m.setMessageBody("" + task.getTaskid());
		try {
			WorkerService.getInstance().sendMessage(m);
		} catch (Exception e1) {
		}
		String workingFolder = Configuration.getInstance()
				.getWorkerTempfolder()
				+ "task" + task.getTaskid() + "/";
		Packer.unpack(task.getFile(), workingFolder);
		TaskDescription td = task.getDescription();
		ProcessBuilder pb = new ProcessBuilder();
		List<String> command = new ArrayList<String>();

		switch (td.getType()) {
		case EXE:
			command.add(workingFolder + td.getExefilename());
			break;
		case JAR:
			command.add(Configuration.getInstance().getJavahome()
					+ "bin/java.exe");
			command.add("-Xmx512m");
			command.add("-jar");
			command.add(workingFolder + td.getExefilename());
			break;
		default:
			break;
		}
		if (td.getDataFilename() != null && !td.getDataFilename().equals("")) {
			command.add(workingFolder + td.getDataFilename());
		}
		pb.command(command);
		try {
			task.setStatus(TaskStatus.RUNNING);
			process = pb.start();
			String resultFile = workingFolder + "result";
			BufferedOutputStream bos = new BufferedOutputStream(
					new FileOutputStream(resultFile));
			BufferedInputStream bis = new BufferedInputStream(process
					.getInputStream());
			int ch = -1;
			while ((ch = bis.read()) != -1) {
				bos.write(ch);
			}
			bos.flush();
			bos.close();
			int returnval = process.waitFor();
			if (returnval == 0) {
				task.setStatus(TaskStatus.DONE);
				m.setType(MessageType.STATUS_DONE);
				m.setMessageBody("" + task.getTaskid());
				WorkerService.getInstance().sendMessage(m);
			} else {
				task.setStatus(TaskStatus.ERROR);
				m.setType(MessageType.STATUS_ERROR);
				m.setMessageBody("" + task.getTaskid());
				WorkerService.getInstance().sendMessage(m);
			}
			// send back result file
			m.setType(MessageType.SENDRESULT);
			FileSender<String> fs = new FileSender<String>("", resultFile);
			fs.start();
			m.setMessageBody(task.getTaskid() + " " + fs.getPort());
			WorkerService.getInstance().sendMessage(m);
			while (fs.isAlive())
				;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (Exception e) {
		}
	}
}
